package com.hframe.http.servlet;

import com.hframe.filter.PageSkipFilter;
import com.hframe.filter.UrlRewrite;
import com.hframe.other.RepeatVerify;
import com.hframe.typefilter.Md5Encoder;
import org.apache.log4j.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 页面跳转过滤类
 *
 * @author heqian
 */
public abstract class HttpSkipServlet extends HttpServlet {
    static Logger log = Logger.getLogger(HttpSkipServlet.class);
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Content-type", "text/html;charset=UTF-8");

        if (DoGet((HttpSkipServletRequest) request, (HttpSkipServletResponse) response)) {
            skipUrl(request, response);
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Content-type", "text/html;charset=UTF-8");

        if (DoPost((HttpSkipServletRequest) request, (HttpSkipServletResponse) response)) {
            skipUrl(request, response);
        }
    }

    @Override
    protected void doHead(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Content-type", "text/html;charset=UTF-8");

        if (DoHead((HttpSkipServletRequest) request, (HttpSkipServletResponse) response)) {
            skipUrl(request, response);
        }
    }

    @Override
    protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Content-type", "text/html;charset=UTF-8");

        if (DoDelete((HttpSkipServletRequest) request, (HttpSkipServletResponse) response)) {
            skipUrl(request, response);
        }
    }

    @Override
    protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Content-type", "text/html;charset=UTF-8");

        if (DoPut((HttpSkipServletRequest) request, (HttpSkipServletResponse) response)) {
            skipUrl(request, response);
        }
    }

    @Override
    protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("Content-type", "text/html;charset=UTF-8");

        if (DoOptions((HttpSkipServletRequest) req, (HttpSkipServletResponse) resp)) {
            skipUrl(req, resp);
        }
    }

    protected void skipUrl(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object skipUrl = req.getAttribute(PageSkipFilter.SkipTag);
        if (null != skipUrl)
            req.getRequestDispatcher((String) skipUrl).forward(req, resp);
    }

    protected abstract boolean DoGet(HttpSkipServletRequest request, HttpSkipServletResponse response) throws ServletException, IOException;

    protected abstract boolean DoPost(HttpSkipServletRequest request, HttpSkipServletResponse response) throws ServletException, IOException;

    protected boolean DoPut(HttpSkipServletRequest request, HttpSkipServletResponse response) throws ServletException, IOException {
        super.doDelete(request, response);
        return false;
    }

    protected boolean DoHead(HttpSkipServletRequest request, HttpSkipServletResponse response) throws ServletException, IOException {
        super.doHead(request, response);
        return false;
    }

    protected boolean DoDelete(HttpSkipServletRequest request, HttpSkipServletResponse response) throws ServletException, IOException {
        super.doDelete(request, response);
        return false;
    }

    protected boolean DoOptions(HttpSkipServletRequest request, HttpSkipServletResponse response) throws ServletException, IOException {
        super.doOptions(request, response);
        return false;
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        super.service(new HttpSkipServletRequest(request), new HttpSkipServletResponse(response));
    }

    /**
     * 创建一个防止重复提交的Token
     *
     * @param request  Http请求
     * @param response Http响应
     */
    protected void createToken(HttpSkipServletRequest request, HttpSkipServletResponse response) {
        String name = this.getClass().getName();
        Cookie cookie = new Cookie(Md5Encoder.encoder(name), RepeatVerify.getToken(request.getSession(), name));
        String requestURI = (String) request.getAttribute(UrlRewrite.requestURI);

        cookie.setPath(null != requestURI ? requestURI : request.getRequestURI());
        response.addCookie(cookie);
    }

    /**
     * 验证数据是否重复提交
     *
     * @param request Http请求
     * @return ture 重复提交， false 第一次提交
     */
    protected boolean verifyToken(HttpSkipServletRequest request) {
        String name = this.getClass().getName();
        Cookie[] cookies = request.getCookies();
        Cookie cookie = getCookie(cookies, Md5Encoder.encoder(name));

        return null != cookie && RepeatVerify.isVerify(request.getSession(), name, cookie.getValue());
    }

    /**
     * 删除防止重复提交的Token
     *
     * @param request Http 响应
     */
    protected void removeToken(HttpSkipServletRequest request) {
        String name = this.getClass().getName();
        RepeatVerify.remove(request.getSession(), name);
    }

    private Cookie getCookie(Cookie[] cookies, String name) {
        for (Cookie item : cookies) {
            if (item.getName().equals(name))
                return item;
        }
        return null;
    }
}
